package com.fowo.api.common.exec;

import com.alibaba.fastjson.JSONObject;
import com.fowo.api.common.lang.ExceptionRunnable;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.util.StreamUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * 提供调用 Shell 环境命令的能力
 */
@Data
@Accessors(chain = true)
public class ShellExec implements ExceptionRunnable {

    /**
     * 要执行的命令
     */
    private String cmd;

    /**
     * 工作目录
     */
    private File cwd;

    /**
     * 环境变量
     */
    private String[] envp;

    /**
     * 最大等于执行完成秒数
     */
    private int timeout = Integer.MAX_VALUE;

    /**
     * 入口参数
     */
    private JSONObject inArgs;

    /**
     * 入口参数 JSON 文件路径
     */
    private File inArgJsonFile;

    /**
     * 是否需要处理返回
     */
    private boolean hasResult;

    /**
     * 返回结果
     */
    private JSONObject result;

    /**
     * 返回结果 JSON 文件路径
     */
    private File resultJsonFile;

    /**
     * 退出值
     */
    private int exitValue;

    /**
     * 是否成功
     */
    private boolean success;

    @Override
    public void run() throws Exception {
        success = false;
        if (hasResult) {
            resultJsonFile = File.createTempFile("result", ".json");
        }

        // 准备命令与参数
        StringBuilder cmdBuilder = new StringBuilder();
        cmdBuilder.append(cmd);
        if (inArgs != null) {
            inArgJsonFile = File.createTempFile("args", ".json");
            try (FileOutputStream fos = new FileOutputStream(inArgJsonFile)) {
                StreamUtils.copy(result.toString(), StandardCharsets.UTF_8, fos);
            }
            cmdBuilder.append(String.format(" --args_json_path=\"%s\"", inArgJsonFile.getAbsolutePath()));
        }
        if (hasResult) {
            cmdBuilder.append(String.format(" --result_json_path=\"%s\"", resultJsonFile.getAbsolutePath()));
        }

        if (cwd == null) {
            // 默认当前目录
            cwd = FileSystems.getDefault().getPath("").toFile();
        }

        // 开始执行
        final Runtime runtime = Runtime.getRuntime();
        final Process exec = runtime.exec(cmdBuilder.toString(), envp, cwd);
        final boolean done = exec.waitFor(timeout, TimeUnit.SECONDS);
        if (done) {
            exitValue = exec.exitValue();
            if (exitValue == 0) {
                success = true;
                if (hasResult) {
                    try(FileInputStream fis = new FileInputStream(resultJsonFile)) {
                        final String resultJson = StreamUtils.copyToString(fis, StandardCharsets.UTF_8);
                    }
                }
            }
        } else {
            // 超时未完成
            if (exec.isAlive()) {
                // 强制退出
                exec.destroy();
            }
            throw new TimeoutException("执行命令未在超时时间内完成");
        }
    }
}
